package com.yunwushanhe.student.util;

import com.alibaba.fastjson.JSON;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTCreator;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.*;
import com.auth0.jwt.interfaces.Claim;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.yunwushanhe.student.bean.ret.Result;
import lombok.extern.slf4j.Slf4j;

import java.util.Calendar;

@Slf4j
public class JwtUtil {
    private static final String SIGN = "@$%$@!GjiW4s4aFFT2165";

    public static <T> String getToken(T t) {
        // 定义过期时间
        Calendar validTime = Calendar.getInstance();
        validTime.add(Calendar.MONTH,1);

        JWTCreator.Builder builder = JWT.create()
                .withClaim(t.getClass().getSimpleName(), JSON.toJSONString(t));
                //这个直接把对象放入进去是为了后面好直接解析出一个对象

        String token = builder.withExpiresAt(validTime.getTime())
                .sign(Algorithm.HMAC256(SIGN));
        return token;
    }

    public static Result<DecodedJWT> verify(String token) {
        String errMsg;
        try {
            DecodedJWT tokenInfo =
                    JWT.require(Algorithm.HMAC256(SIGN)).build().verify(token);
            return Result.ok(tokenInfo);
        }catch (AlgorithmMismatchException e) {
            errMsg = "算法不匹配";
            log.error(errMsg,e);
        }catch (SignatureVerificationException e) {
            errMsg = "签名不匹配";
            log.error(errMsg,e);
        }catch (TokenExpiredException e) {
            errMsg = "令牌失效";
            log.error(errMsg,e);
        }catch (InvalidClaimException e) {
            errMsg = "声明无效";
            log.error(errMsg,e);
        }catch (Exception e) {
            errMsg = "校验令牌失败";
            log.error(errMsg,e);
        }
        return Result.fail(errMsg);
    }

    /**
     * 这个方法是把 DecodedJWT 中从token中解析出来的信息封装到原本的类中
     */
    public static <T> T parse(DecodedJWT decodedJWT, Class<T> clz) {
        Claim claim = decodedJWT.getClaim(clz.getSimpleName());
        if(claim == null){
            return null;
        }
        return JSON.parseObject(claim.asString(),clz);
    }
}
